home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Presentations / Presentations ’96 / Papers ’96 / Book of Practical Objects / BasicObjects ƒ / CFIFOQueue.cp < prev    next >
Encoding:
Text File  |  1996-06-22  |  4.0 KB  |  188 lines  |  [TEXT/CWIE]

  1. #include "CFIFOQueue.h"
  2.  
  3.         CFIFOQueue::CFIFOQueue(Boolean autoExpand, Boolean onlyLongs)
  4. {
  5.     fOnlyLongs = onlyLongs;
  6.     fAutoExpand = autoExpand;
  7.     
  8.     fQueueElementSize = sizeof(long);
  9.     fQueueMaxElements = kDefaultQueueSize;
  10.     fQueueElements = 0;
  11.     
  12.     fQueueHead = NewHandle(fQueueElementSize * fQueueMaxElements);
  13.     if (MemError() != noErr)
  14.         throw MemError();
  15. }
  16.  
  17.  
  18.         CFIFOQueue::CFIFOQueue(long elementSize, long maxElements, Boolean autoExpand, Boolean onlyLongs)
  19. {
  20.     fOnlyLongs = onlyLongs;
  21.     fAutoExpand = autoExpand;
  22.     
  23.     fQueueElementSize = elementSize;
  24.     fQueueMaxElements = maxElements;
  25.     fQueueElements = 0;
  26.     
  27.     fQueueHead = NewHandle(fQueueElementSize * fQueueMaxElements);
  28.     if (MemError() != noErr)
  29.         throw MemError();
  30.  
  31. }
  32.  
  33.  
  34.         CFIFOQueue::~CFIFOQueue(void)
  35. {
  36.     DisposHandle(fQueueHead);
  37. }
  38.  
  39.  
  40.     
  41. OSErr    CFIFOQueue::SetMaxQueueSize(long maxElements)    // Could return an error (-108, or QueueTooBig)
  42. {
  43.     long    theSize;
  44.     OSErr    err;
  45.  
  46.     // First an easy check
  47.     if (maxElements < fQueueElements)        // Do we have more than that already?
  48.         return (kQueueAlreadyTooBig);
  49.     
  50.     // OK, so now we just try to resize the queue
  51.     theSize = fQueueElementSize * maxElements;
  52.     SetHandleSize(fQueueHead, theSize);
  53.     err = MemError();
  54.     
  55.     if (err == noErr)
  56.         fQueueMaxElements = maxElements;
  57.     
  58.     return (err);
  59. }
  60.  
  61.  
  62. long    CFIFOQueue::GetMaxQueueSize(void)
  63. {
  64.     return (fQueueMaxElements);
  65. }
  66.  
  67.  
  68.  
  69. long    CFIFOQueue::GetQueueElementSize(void)
  70. {
  71.     return (fQueueElementSize);
  72. }
  73.  
  74.  
  75. Boolean    CFIFOQueue::AddElement(void *theData)            // The address to take data from
  76. {
  77.     long    tryToGrowBy;
  78.     long    newQueueCount;
  79.     Size    theSize;
  80.     OSErr    err;
  81.     Boolean    done;
  82.     Boolean    result = true;        // Assume that we work
  83.  
  84.     if (fQueueElements < (fQueueMaxElements - 1))    // Go ahead and add it, we have space
  85.         AddOneElementToQueue(theData);
  86.     else {
  87.             if (fAutoExpand)        // Grow the queue by the default number of elements
  88.             {
  89.                 done = false;
  90.                 tryToGrowBy = kDefaultQueueSize;
  91.                 do {
  92.                     try
  93.                     {
  94.                         newQueueCount = fQueueMaxElements + tryToGrowBy;
  95.                         theSize = newQueueCount * fQueueElementSize;
  96.                         SetHandleSize(fQueueHead, theSize);
  97.                         err = MemError();
  98.                         if (err != noErr)
  99.                             throw ((OSErr) err);
  100.                         fQueueMaxElements = newQueueCount;
  101.                         AddOneElementToQueue(theData);
  102.                         done = true;
  103.                     }
  104.                     catch (OSErr error)
  105.                     {
  106.                         if (tryToGrowBy > 1)
  107.                         {
  108.                             tryToGrowBy = 1;
  109.                         }
  110.                         else {
  111.                                 done = true;
  112.                                 result = false;
  113.                              }
  114.                     }
  115.                 } while (!done);
  116.             }            // if (fAutoExpand)
  117.             else {
  118.                     result = false;        // Too big, and not allowed to grow, failure
  119.                  }
  120.          }
  121.          
  122.     return (result);
  123. }
  124.  
  125.  
  126. // theData needs to be storage allocated already for objects, or if fOnlyLongs
  127. // has been set, then it is the address of a long to store the result in.
  128. Boolean    CFIFOQueue::GetFrontElement(void *theData)
  129. {
  130.     Ptr        topPtr, startPtr;
  131.     long    theByteCount;
  132.  
  133.     if (fQueueElements == 0)
  134.         return (false);
  135.  
  136.     if (fOnlyLongs)
  137.     {
  138.         *(long *)theData = **(long**)fQueueHead;
  139.     }
  140.     else {
  141.             BlockMove(*fQueueHead, theData, fQueueElementSize);
  142.          }
  143.     
  144.     fQueueElements--;
  145.     // Now go and shift the elements up in the queue
  146.     if (fQueueElements > 0)
  147.     {
  148.         theByteCount = fQueueElements * fQueueElementSize;
  149.         topPtr = *fQueueHead;
  150.         startPtr = topPtr + fQueueElementSize;
  151.         BlockMoveData(startPtr, topPtr, theByteCount);
  152.     }
  153.  
  154.     return (true);
  155. }
  156.  
  157.  
  158.  
  159. long    CFIFOQueue::GetQueueLength(void)
  160. {
  161.     return (fQueueElements);
  162. }
  163.  
  164.  
  165. // This method KNOWS that there is enough storage to move something into the queue
  166. // so it doesn't have to do any additional checking.
  167. // Please make sure that theData is at least word aligned if you want this to run on
  168. // a 68000 machine.
  169. void    CFIFOQueue::AddOneElementToQueue(void *theData)
  170. {
  171.     Ptr    destPtr;
  172.     
  173.     if (fOnlyLongs)        // We get to cheat and use theData as a long
  174.     {
  175.         (*(long**)fQueueHead)[fQueueElements] = (long) theData;
  176.     }
  177.     else {
  178.             // Figure the offset first for slightly better instruction scheduling on PPC
  179.             destPtr = (Ptr) (fQueueElementSize * fQueueElements);
  180.             destPtr += *fQueueHead;
  181.  
  182.             BlockMoveData(theData, destPtr, fQueueElementSize);
  183.          }
  184.     
  185.     fQueueElements++;
  186. }
  187.  
  188.